/*
	filename:		CCardRegion.h
	author:			Rico Roberto Zu�iga
	last modified:	9/12/03

	description:	Interface for card region data structure.
*/

#ifndef CCARDREGION_H
#define CCARDREGION_H

#include "CCardStack.h"
#include "Query.h"

#include <QPoint>
#include <QPair>
#include <QRect>
#include <QPixmap>
#include <QMessageBox>

namespace CardGraphics {
  enum DragMode {DragNone, DragAllCards, DragCard, DragTopCard,
                 DragFaceUpCards};
  enum StackAttribute {StackInvisible=0, StackVisible=1, StackFaceUp=2,
                       Stack3d=4, StackDrag=8, StackDrop=16};
  enum DropReq {NoReqs=0, ReqSingleCard=1, ReqOppColor=2, ReqRed=4,
                ReqBlack=8, ReqNotLower=16, ReqNotHigher=32, ReqEqual=48,
                ReqNotEqual=64, ReqAdjacent=192, ReqSameSuit=256, ReqAce=512,
                ReqKing=1024};
  typedef QPair<QRect,QPixmap> CardDrawInfo;
  typedef QList<CardDrawInfo> CardDrawList;
}

class CCardRegion
{
	public:
    CCardRegion(//unsigned int reqs=CardGraphics::NoReqs,
//                 CardGraphics::DragMode dmode=CardGraphics::DragNone,
                QPoint pos=QPoint(), QSize off=QSize(),
                CardGraphics::CardSymbol symb=CardGraphics::NoSymbol,
                unsigned int attribs=(CardGraphics::StackVisible | CardGraphics::StackFaceUp)
               )
      : /*dropReqs(reqs), dragMode(dmode),*/
        position(pos), offset(off), symbol(symb),
        attributes(attribs){

      Query::debugOut("Generating a new card region at (",2);
      Query::debugValue(position.x(),2);
      Query::debugOut(",",2);
      Query::debugValue(position.y(),2);
      Query::debugOut(")\n",2);
      if (!deck) {
        deck = new QPixmap;
        if (!deck->load(":/deck.bmp")) {
          QMessageBox::warning(NULL, "Initialize Deck",
                               "The deck image file could not be loaded.",
                               QMessageBox::Cancel);
        }
        cardSize.setWidth(CardGraphics::CARDWIDTH);
        cardSize.setHeight(CardGraphics::CARDHEIGHT);
      }
    }

		void SetCardStack(const CCardStack& cs) {
      cardStack = &cs;
      Query::debugOut("Set stack has ", 3);
      Query::debugValue(cardStack->Size(), 3);
      Query::debugOut(" cards.\n", 3);
    }
// 		CCardStack* GetCardStack()						{ return &InternalStack; }
//
		void SetPosition(const QPoint& p) {
      position = p;
    }
		QPoint GetPosition() const {
      return position;
    }
    QRect GetRect() const {
      QSize stackSize;
      if (attributes & CardGraphics::Stack3d)
        stackSize = cardSize + offset*(cardStack->Size()/factorFor3d);
      else
        stackSize = cardSize + offset*(cardStack->Size()-1);
      return QRect(position, stackSize);
    }
    int GetClickedIndex(const QPoint &click) const {
      bool is3d = attributes & CardGraphics::Stack3d;
      int topIndex = cardStack->Size() - 1;
      if (is3d)
        topIndex /= factorFor3d;

      QPoint topCardPos = position + QPoint(offset.width()*topIndex,
                                            offset.height()*topIndex);
      QRect card(topCardPos, cardSize);

      for (int i=topIndex; i>=0; i--) {
        if (card.contains(click)) {
          if (is3d) {
            return topIndex;
          }
          else {
            return i;
          }
        }
        card.translate(-offset.width(), -offset.height());
      }
      return -1;
    }

		void SetOffset(QSize o) {
      offset = o;
    }
		QSize GetOffset() const {
      return offset;
    }

//     void InitCardFaces()							{ InternalStack.SetCardsFaceUp(Attributes&CRD_FACEUP); }

    bool IsVisible() const {
      return attributes & CardGraphics::StackVisible;
    }
//     bool FaceUp() const {
//       return attributes & CardGraphics::StackFaceUp;
//     }
//     bool FaceDown() const {
//       return !FaceUp();
//     }
		bool CanDrag() const {
      return attributes & CardGraphics::StackDrag;
    }

//     void SetCardFaceUp(bool fTrue, int Idx)			{ InternalStack[Idx].SetFaceUp(fTrue); }
//     bool CardFaceUp(int Idx)						{ InternalStack[Idx].FaceUp(); }
//
//     void SetDragMode(CardGraphics::DragMode mode) {
//       dragMode = mode;
//     }
//     CardGraphics::DragMode GetDragMode() const {
//       return dragMode;
//     }

    void SetSymbol(CardGraphics::CardSymbol symb) {
      symbol = symb;
    }

// 		void SetDropReqs(unsigned int reqs) {
//       dropReqs = reqs;
//     }
		void SetAttributes(unsigned int attr) {
      attributes = attr;
    }
    void AddAttributes(unsigned int attr) {
      attributes |= attr;
    }
    void RemoveAttributes(unsigned int attr) {
      attributes &= ~attr;
    }
    unsigned int GetAttributes() const {
      return attributes;
    }

//---------------------------------------------------------------------------------------
//Defined in CCardRegion.cpp

		bool CanDrop(const CCardStack& stack);

    CardGraphics::CardDrawList getDrawList();
// 		void DrawCardStack();
// 		void DrawCardStack(SDL_Surface *s);
//
// //		void AnimateStack();
//
// 		void InitCardCoords();
// 		int  GetOverlapRatio(int x, int y, int width, int height);
//
// 		bool PtInStack(int x, int y); //Imperfect, needs tweaking
// 		bool PtOnTop(int x, int y);
//
// 		int GetStackWidth();
// 		int GetStackHeight();

//---------------------------------------------------------------------------------------
//CCardStack object wrappers
//
// 		void        NewDeck()							{ InternalStack.NewDeck();  }
// 		void        Shuffle()							{ InternalStack.Shuffle();  }
// 		void        Clear()								{ InternalStack.Clear();    }
// 		void        Reverse()							{ InternalStack.Reverse();  }
//
// 		void        Push(CCard card)					{ InternalStack.Push(card); }
// 		void        Push(CCardStack cs)					{ InternalStack.Push(cs);   }
//
// 		void		AddJokers(int jokers)				{ InternalStack.AddJokers(jokers); }
//
//     bool		Empty()								{ return InternalStack.Empty(); }
// 		int			Size()								{ return InternalStack.Size(); }
//
// 		CCard       Pop()								{ return InternalStack.Pop();      }
// 		CCardStack  Pop(int items)						{ return InternalStack.Pop(items); }
//
// 		CCard		RemoveCard(int index)				{ return InternalStack.RemoveCard(index); }
//
// 		int			GetClickedCard(int x, int y)		{ return InternalStack.GetClickedCard(x, y); }
// 		CCard		GetCard(int index)					{ return InternalStack.GetCard(index); }
//
// //---------------------------------------------------------------------------------------
//
// 		int Id;
//
	private:

    int getDeckIndex(int cardIndex);
//    unsigned int dropReqs;

//     CardGraphics::DragMode dragMode;

    const CCardStack* cardStack;
    QPoint position;
    QSize offset;
    CardGraphics::CardSymbol symbol;
    unsigned int attributes;

    static QPixmap* deck;
    static QSize cardSize;
    static const int factorFor3d = 4;
};

#endif //CCARDREGION_H
